package com.huangxunyi.GUET;

import java.io.*;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Collections;
import java.util.Vector;

/**
 * //=======================================================
 * //		          .----.
 * //		       _.'__    `.
 * //		   .--(^)(^^)---/!\
 * //		 .' @          /!!!\
 * //		 :         ,    !!!!
 * //		  `-..__.-' _.-\!!!/
 * //		        `;_:    `"'
 * //		      .'"""""`.
 * //		     /,  ya ,\\
 * //		    //狗神保佑\\
 * //		    `-._______.-'
 * //		    ___`. | .'___
 * //		   (______|______)
 * //=======================================================
 * Created by huang on 2017/2/25.
 */
public class IPClientUtils {

    /**
     * @func changeStr
     * @brief add delta to each byte of string
     */
    public static String changeStr(String str, int delta) {
        byte[] tmp = str.getBytes();
        for (int i = 0; i < tmp.length; i++) {
            tmp[i] += delta;
        }
        return new String(tmp);
    }

    /**
     * @brief return random interger [start, start + delta)
     */
    public static int getRandomInt(int start, int delta) {
        return (int) (start + Math.random() * delta);
    }

    /**
     * @brief generate a random string of length
     */
    public static String getRandomString(int length) {
        byte[] choose = "0123456789abcdef".getBytes();
        byte[] tmp = new byte[length];
        for (int i = 0; i < tmp.length; i++) {
            tmp[i] = choose[(int) (Math.random() * choose.length)];
        }
        return new String(tmp);
    }

    /**
     * @func md5String
     * @brief do the md5 encrypt of the string(arg0), then get the hex string of
     * each byte of the encryption string.
     */
    public static String md5String(String str) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        byte[] aftetByet = (digest != null) ? digest.digest(str.getBytes()) : new byte[0];
        StringBuilder result = new StringBuilder();
        for (byte b : aftetByet) {
            String tmp = Integer.toHexString(b & 0xff);
            if (tmp.length() < 2) {
                tmp = "0" + tmp;
            }
            result.append(tmp);
        }
        return result.toString();
    }

    /**
     * @func flow_encrypt
     * @brief use the key to encrypt the password, this is a flow encryption
     * algorithm.
     */
    public static String flowEncrypt(String password, int key) {
        byte[] passByte = password.getBytes();
        int vkey = key;
        for (int i = 0; i < password.length(); i++) {
            int c = passByte[i];
            int tmp = vkey;
            tmp = (tmp & 0xffff) >> 8;
            int d = tmp & 0xff;
            c = d ^ c;
            passByte[i] = (byte) c;
            int e = vkey & 0xffff;
            e = (e + c) & 0xffff;
            e = (e * 0xce6d) & 0xffff;
            e = (e + 0x58bf) & 0xffff;
            vkey = e;
        }
        return new String(passByte);
    }

    public static byte[] short2byte(short num) {
        byte[] b = new byte[2];
        int offset = 0;
        for (int i = 0; i < b.length; i++) {
            b[i] = (byte) ((num >> offset) & 0xff);
            offset += 8;
        }
        return b;
    }

    public static short byte2short(byte[] b, int start) {
        short result = 0;
        try {
            int offset = 0;
            for (int i = start; i < start + 4; i++) {
                result += (1 << offset) * (b[i] & 0xff);
                offset += 8;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static byte[] int2byte(int num) {
        byte[] b = new byte[4];
        int offset = 0;
        for (int i = 0; i < b.length; i++) {
            b[i] = (byte) ((num >> offset) & 0xff);
            offset += 8;
        }
        return b;
    }

    public static int byte2int(byte[] b, int start) {
        int result = 0;
        try {
            int offset = 0;
            for (int i = start; i < start + 4; i++) {
                result += (1 << offset) * (b[i] & 0xff);
                offset += 8;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static byte[] long2byte(long num) {
        byte[] b = new byte[8];
        int offset = 0;
        for (int i = 0; i < b.length; i++) {
            b[i] = (byte) ((num >> offset) & 0xff);
            offset += 8;
        }
        return b;
    }

    public static long byte2long(byte[] b, int start) {
        long result = 0;
        try {
            int offset = 0;
            for (int i = start; i < start + 8; i++) {
                result += (1L << offset) * (b[i] & 0xff);
                offset += 8;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static double byte2double(byte[] b, int start) {
        long n = byte2long(b, start);
        if (n == 0) {
            return 0;
        }
        double mantissa = n & 0x000fffffffffffffL;
        mantissa += (1L << (13 * 4));
        mantissa /= (1L << (13 * 4));
        int exponent = (int) ((n & 0x7ff0000000000000L) >> 13 * 4);
        mantissa *= Math.pow(2, exponent - 1023);
        if (n < 0) {
            mantissa *= -1;
        }
        return mantissa;
    }

    public synchronized static Vector<Vector<String>> loadAccounts(String accsFileName)
            throws IOException {
        Vector<Vector<String>> accs = new Vector<Vector<String>>();
        File accsFile = new File(accsFileName);
        if (!accsFile.exists()) {
            accsFile.createNewFile();
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(accsFile), "utf-8"));
        String acc;
        while ((acc = br.readLine()) != null) {
            Vector<String> accAry = new Vector<String>();
            Collections.addAll(accAry, acc.split(","));
            try {
                String[] moneyInfo = accAry.get(2).split("月");
                int a = Integer.parseInt(moneyInfo[0]);
                int curMonth = Calendar.getInstance().get(Calendar.MONDAY) + 1;
                if (a != curMonth) {
                    accAry.set(2, "");
                }
            } catch (Exception ignored) {
            }
            for (int i = accAry.size(); i < 4; i++) {
                accAry.add("");
            }
            accs.add(accAry);
        }
        br.close();
        return accs;
    }

    public synchronized static void writeAccounts(String accsFileName,
                                                  Vector<Vector<String>> accs) throws IOException {
        PrintStream ps = new PrintStream(new FileOutputStream(accsFileName),false,"utf-8");
        for (Vector<String> v : accs) {
            try {
                String[] strings = new String[4];
                v.toArray(strings);
                if (!strings[3].equals("用户名或密码错误")) {
                    strings[3] = "";
                }
                ps.println(strings[0] + "," + strings[1] + "," + strings[2]
                        + "," + strings[3]);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ps.close();
    }

    public static String getProjectPath() {
        String filePath;
        try {
            filePath = URLDecoder.decode(Main.class.getProtectionDomain()
                    .getCodeSource().getLocation().getFile(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            filePath = "";
            e.printStackTrace();
        }
        if (filePath.endsWith(".jar")) {
            filePath = filePath.substring(0,
                    filePath.lastIndexOf(File.separator) + 1);
        }
        File file = new File(filePath);
        filePath = file.getAbsolutePath() + File.separator;

        return filePath;
    }
}
